<?php

namespace app\merchant\model;

use app\common\enum\order\PayStatus as PayStatusEnum;
use app\common\enum\order\Status as OrderStatusEnum;
use app\common\library\helper;
use app\common\model\Store as StoreModel;


/**
 * 商城模型
 * Class Store
 * @package app\store\model
 */
class Store extends StoreModel
{
    /* @var Goods $GoodsModel */
    private $GoodsModel;

    /* @var Order $GoodsModel */
    private $OrderModel;

    /* @var User $GoodsModel */
    private $UserModel;

    /**
     * 构造方法
     */
    public function initialize()
    {
        parent::initialize();
        /* 初始化模型 */
        $this->GoodsModel = new Goods;
        $this->OrderModel = new Order;
        $this->UserModel = new User;
    }

    /**
     * 后台首页数据
     * @return array
     * @throws \think\Exception
     */
    public function getHomeData($param)
    {
        //商城统计
        $store = [
            'goods_num' => $this->getGoodsTotal(),//商品总量 ok
            'order_num' => $this->getOrderTotal(),//已支付订单总量 ok
            'user_num' => $this->getUserTotal(),//用户总量 ok
            'comment_num' => $this->getCommentTotal(),//订单评论总量 ok
        ];



        //计算今日的数据
        $today = date('Y-m-d');
        $yesterday = date('Y-m-d', strtotime('-1 day'));

        //今日收入金额
        $todaywechatpay = $this->getWxPay($today,$today);//微信支付
        $todaymoneypay = $this->getOrderYueTotalPrice($today,$today);//余额支付
        $todaybackmoney = $this->getRefundTotal($today,$today);//分红退款
        $todaydealermoney = $this->getDealerSetted($today,$today);//已发放佣金
        $todayall = bcsub(($todaywechatpay+$todaymoneypay),($todaybackmoney+$todaydealermoney),2);

        //昨日收入金额
        $ytdwechatpay = $this->getWxPay($yesterday,$yesterday);//微信支付
        $ytdmoneypay = $this->getOrderYueTotalPrice($yesterday,$yesterday);//余额支付
        $ytdbackmoney = $this->getRefundTotal($yesterday,$yesterday);//分红退款
        $ytddealermoney = $this->getDealerSetted($yesterday,$yesterday);//已发放佣金
        $ytdall = bcsub(($ytdwechatpay+$ytdmoneypay),($ytdbackmoney+$ytddealermoney),2);


        //今日
        $tdy = [
            'tday' => $todayall,//今日收入金额
            'ytd' => $ytdall,//昨日收入金额
            'tdayOrder' => $this->getOrderTotal($today,$today),//今日支付订单数
            'ytdOrder' => $this->getOrderTotal($yesterday,$yesterday),//昨日支付订单数
            'tdayPayUser' => $this->getPayOrderUserTotal($today,$today),//今日支付人数
            'ytdPayUser' => $this->getPayOrderUserTotal($yesterday,$yesterday),//昨日支付人数
            'tdayVisitorUser' => $this->getVisitorUser($today,$today),//今日访客数
            'ytdVisitorUser' => $this->getVisitorUser($yesterday,$yesterday),//昨日访客数

        ];



        //获取本月第一天和最后一天
        $startMouthNow = $this->getthemonth($today)['0'];
        $endMouthNow = $this->getthemonth($today)['1'];

        //本月收入金额
        $mouthwechatpay = $this->getWxPay($startMouthNow,$endMouthNow);//微信支付
        $mouthmoneypay = $this->getOrderYueTotalPrice($startMouthNow,$endMouthNow);//余额支付
        $mouthbackmoney = $this->getRefundTotal($startMouthNow,$endMouthNow);//分红退款
        $mouthdealermoney = $this->getDealerSetted($startMouthNow,$endMouthNow);//已发放佣金
        $mouthall = bcsub(($mouthwechatpay+$mouthmoneypay),($mouthbackmoney+$mouthdealermoney),2);

        //获取本月第一天和最后一天
        $startMouthYe = date('Y-m-d', strtotime(date('Y-m-01') . ' -1 month'));
        $endMouthYe = date('Y-m-d', strtotime(date('Y-m-01') . ' -1 day')); // 计算出本月第一天再减一天


        //上月收入金额
        $yemouthwechatpay = $this->getWxPay($startMouthYe,$endMouthYe);//微信支付
        $yemouthmoneypay = $this->getOrderYueTotalPrice($startMouthYe,$endMouthYe);//余额支付
        $yemouthbackmoney = $this->getRefundTotal($startMouthYe,$endMouthYe);//分红退款
        $yemouthdealermoney = $this->getDealerSetted($startMouthYe,$endMouthYe);//已发放佣金
        $yemouthall = bcsub(($yemouthwechatpay+$yemouthmoneypay),($yemouthbackmoney+$yemouthdealermoney),2);


        //本月
        $mouth = [
            'tday' => $mouthall,//本月收入金额
            'ytd' => $yemouthall,//上月收入金额
            'tdayOrder' => $this->getOrderTotal($startMouthNow,$endMouthNow),//本月支付订单数
            'ytdOrder' => $this->getOrderTotal($startMouthYe,$endMouthYe),//上月支付订单数
            'tdayPayUser' => $this->getPayOrderUserTotal($startMouthNow,$endMouthNow),//本月支付人数
            'ytdPayUser' => $this->getPayOrderUserTotal($startMouthYe,$endMouthYe),//上月支付人数
            'tdayVisitorUser' => $this->getVisitorUser($startMouthNow,$endMouthNow),//本月访客数
            'ytdVisitorUser' => $this->getVisitorUser($startMouthYe,$endMouthYe),//上月访客数
        ];


        //动态订单--查询最新的5条
        $orderDymic = $this->orderDymic();

        //商品排行榜
        $goodsSale = $this->goodsSale();

        //用户消费榜
        $userSale = $this->userSale();


        $data = compact('store','tdy','mouth','orderDymic','goodsSale','userSale');

        return $data;
    }



    /**
     * 实时数据概况
     * @param $days
     * @return array
     * @throws \think\Exception
     */
    public function online($param)
    {

        //实时数据--默认时间是今天
        $starttime = date('Y-m-d');
        $endtime = date('Y-m-d');

        if(isset($param['starttime']) && $param['starttime']){
            $starttime = $param['starttime'];
            $endtime = $param['endtime'];
        }

        $wechatpay = $this->getWxPay($starttime,$endtime);//微信支付  ok
        $moneypay = $this->getOrderYueTotalPrice($starttime,$endtime);//余额支付 ok
        $backmoney = $this->getRefundTotal($starttime,$endtime);//分红退款 ok
        $dealermoney = $this->getDealerMoney($starttime,$endtime);//待发放佣金 ok
        $all = bcsub(($moneypay+$wechatpay),($backmoney+$dealermoney),2); //ok

        //分割时间
        $dataTimeOld = $this->getSchemeDate($starttime,$endtime,$num=4);

        $online = [

            //收益统计
            'income' => [
                'all' => $all,
                'wechatpay' => $wechatpay,
                'moneypay' => $moneypay,
                'backmoney' => $backmoney,
                'dealermoney' => $dealermoney,

            ],
            //订单数量统计
            'order' => [
                'order_num' => $this->getOrderAll($starttime,$endtime),//订单总笔数 ok
                'pay_num' => $this->getPayOrder($starttime,$endtime),//付款笔数 ok
                'back_num' => $this->getRefundNum($starttime,$endtime),//分红退款笔数 ok
                'balance_num' => $this->getOrderYueTotalPrice($starttime,$endtime),//余额支付笔数 ok
                'dealer_num' => $this->getDealerTotal($starttime,$endtime),//待发放佣金笔数 ok

            ],


            //用户实时概况
            'user' => [
                'date' => $dataTimeOld,//时间
                'order_total' => $this->getChargeUser($dataTimeOld),//充值用户 ok
                'order_total_price' => $this->getPayUser($dataTimeOld)//下单用户 ok

            ],

        ];

        return $online;

    }



    /**
     * 用户访客数量
     * @param $days
     * @return array
     * @throws \think\Exception
     */
    public function userVisitor($param)
    {

        //用户访客数量
        $starttime = date('Y-m-d');
        $endtime = date('Y-m-d');

        if(isset($param['starttime']) && $param['starttime']){
            $starttime = $param['starttime'];
            $endtime = $param['endtime'];
        }
        $userVisitor = $this->getVisitorUser($starttime,$endtime);//用户访客数量

        return $userVisitor;

    }


    /**
     * 交易走势
     * @param $days
     * @return array
     * @throws \think\Exception
     */
    public function echarts($param)
    {

        //默认一周
        $lately7days = $this->getLately7days();
        if(isset($param['starttime']) && $param['starttime']){
            $starttime = $param['starttime'];
            $endtime = $param['endtime'];
            $lately7days = $this->periodDate($starttime,$endtime);

        }

        $echarts = [
            // 最近七天日期
            'date' => $lately7days,
            'order_total' => $this->getOrderTotalByDate($lately7days),
            'order_total_price' => $this->getOrderTotalPriceByDate($lately7days)

        ];

        return $echarts;

    }


    /**
     * 用户消费榜
     * @param $days
     * @return array
     * @throws \think\Exception
     */
    private function userSale()
    {

        $user = db('user')
            ->where(['wxapp_id'=>self::$wxapp_id,'is_delete'=>0])
            ->field(['user_id','nickName','avatarUrl','pay_money'])
            ->order('pay_money desc')
            ->limit(5)
            ->select()->toArray();
        return $user;
    }



    /**
     * 商品排行榜
     * @param $days
     * @return array
     * @throws \think\Exception
     */
    private function goodsSale()
    {

        $goods = db('goods')
            ->alias('a')
            ->join('yoshop_goods_image b','a.goods_id=b.goods_id')
            ->join('yoshop_upload_file c','c.file_id=b.image_id')
            ->where(['a.wxapp_id'=>self::$wxapp_id,'a.is_delete'=>0])
            ->field(['a.goods_id','a.sales_actual','c.storage','c.file_url','c.file_name'])
            ->order('a.sales_actual desc')
            ->limit(5)
            ->select()->toArray();

        foreach ($goods as $k=>&$v){
            if ($v['storage'] === 'local') {
                $v['image'] =  base_url() . 'uploads/' . $v['file_name'];
            }else{
                $v['image'] =  $v['file_url'] . '/' . $v['file_name'];
            }
            $v['salemoney'] =  db('order_goods')
                ->alias('a')
                ->join('yoshop_order b','a.order_id=b.order_id')
                ->where(['a.goods_id'=>$v['goods_id'],'b.pay_status'=>20,'b.order_status'=>['<>',20]])
                ->sum('total_pay_price');

        }


        return $goods;
    }



    /**
     * 动态订单--查询最新的5条
     * @param $days
     * @return array
     * @throws \think\Exception
     */
    private function orderDymic()
    {

        //5 爆品礼订单 10普通订单 20砍价订单 30秒杀订单 40 购买会员订单 50当面付订单
        $wxapp_id = self::$wxapp_id;
        $where = "`a`.`wxapp_id` = {$wxapp_id} AND `a`.`pay_status` = 20 ";

        $db = db();
        $sql = "
        (SELECT `a`.`order_id`,`a`.`pay_time`,`b`.`nickName`,`a`.`order_source`
        FROM `yoshop_order` `a` LEFT JOIN `yoshop_user` `b` ON `a`.`user_id`=`b`.`user_id` 
        WHERE  {$where})
        UNION
        (SELECT `a`.`order_id`,`a`.`pay_time`,`b`.`nickName`,5 as `order_source`   
        FROM `yoshop_gifts_order` `a` LEFT JOIN `yoshop_user` `b` ON `a`.`user_id`=`b`.`user_id` 
        WHERE  {$where})
        ORDER BY `pay_time` DESC LIMIT 0,5
        ";

        $list = $db->query($sql);

        foreach($list as $k=>&$v){
            if($v['order_source']==5){//爆品礼
                $title = db('gifts_order_goods')
                    ->where(['order_id'=>$v['order_id']])
                    ->value('gifts_title');
                $v['title'] = '购买了  '.$title.'  爆品';

            }
            if($v['order_source']==50){//当面付订单
                $v['title'] = '支付了 当面付 订单';
            }
            if($v['order_source']==40){//购买会员订单
                $title = db('wxapp_card_order_plan')
                    ->where(['order_id'=>$v['order_id']])
                    ->value('card_title');
                $v['title'] = '购买了  '.$title.'  会员';
            }
            if($v['order_source']==10){//普通订单
                $title = db('order_goods')
                    ->where(['order_id'=>$v['order_id']])
                    ->value('goods_name');
                $v['title'] = '购买了  '.$title.'  商品';
            }
            if($v['order_source']==30){//秒杀订单
                $title = db('order_goods')
                    ->where(['order_id'=>$v['order_id']])
                    ->value('goods_name');
                $v['title'] = '秒杀了  '.$title.'  商品';
            }
            $v['pay_time'] = date('Y-m-d H:i:s',$v['pay_time']);
        }

        return $list;
    }



    /**
     * 获取访客数 (指定日期)
     * @param $days
     * @return array
     * @throws \think\Exception
     */
    private function getVisitorUser($start = null ,$end = null)
    {
        $filter = [
            'wxapp_id' => self::$wxapp_id,
            'create_time' =>  [
                ['>=', strtotime($start)],
                ['<', strtotime($end) + 86400],
            ]
        ];

        $count = db('store_shop_visitor')
            ->where($filter)
            ->count();
        return $count;

    }


    /**
     * 获取某个时间段的微信支付的总额
     * @param null $day
     * @return string
     */
    private function getWxPay($start = null,$end = null)
    {
        return helper::number2($this->OrderModel->getWxPay($start, $end));
    }






    /**
     * 获取待发放佣金笔数 (指定日期)
     * @param $days
     * @return array
     * @throws \think\Exception
     */
    private function getDealerMoney($startday = null,$endtime = null)
    {
        $where = [
            'is_settled' => 0,
            'wxapp_id' => self::$wxapp_id,
            'create_time' =>  [
                ['>=', strtotime($startday)],
                ['<', strtotime($endtime) + 86400],
            ]
        ];

        $money = db('dealer_order')
            ->where($where)
            ->sum('first_money');

        return $money;
    }

    /**
     * 获取某天的余额支付总金额
     */
    private function getOrderYueTotalPrice($startday = null,$endtime = null){
        return helper::number2($this->OrderModel->getOrderYueTotalPrice($startday, $endtime));
    }



    /**
     * 最近七天日期
     */
    private function getLately7days()
    {
        // 获取当前周几
        $date = [];
        for ($i = 0; $i < 7; $i++) {
            $date[] = date('Y-m-d', strtotime('-' . $i . ' days'));
        }
        return array_reverse($date);
    }



    /**
     * 获取商品总量
     * @return string
     * @throws \think\Exception
     */
    private function getGoodsTotal()
    {
        return number_format($this->GoodsModel->getGoodsTotal());
    }

    /**
     * 获取用户总量
     * @param null $day
     * @return string
     * @throws \think\Exception
     */
    private function getUserTotal($day = null)
    {
        return number_format($this->UserModel->getUserTotal($day));
    }



    /**
     * 获取订单总量 (指定日期)
     * @param $days
     * @return array
     * @throws \think\Exception
     */
    private function getOrderTotalByDate($days)
    {
        $data = [];
        foreach ($days as $day) {
            $data[] = $this->getOrderTotal($day,$day);
        }
        return $data;
    }


    /**
     * 获取订单总量
     * @param null $day
     * @return string
     * @throws \think\Exception
     */
    private function getOrderTotal($startday = null, $endday = null)
    {
        return number_format($this->OrderModel->getPayOrderTotal($startday, $endday));
    }


    /**
     * 获取所有订单总量
     * @param null $day
     * @return string
     * @throws \think\Exception
     */
    private function getOrderAll($startday = null,$endtime = null)
    {
        return number_format($this->OrderModel->getOrderAll($startday, $endtime));
    }


    /**
     * 获取付款订单总量
     * @param null $day
     * @return string
     * @throws \think\Exception
     */
    private function getPayOrder($startday = null,$endtime = null)
    {
        return number_format($this->OrderModel->getPayOrderTotal($startday, $endtime));
    }


    /**
     * 获取充值用户总量 (指定日期)
     * @param $days
     * @return array
     * @throws \think\Exception
     */
    private function getChargeUser($days)
    {

        $data = [];
        foreach ($days as $day) {
            $data[] = $this->getChargeUserTotal($day);
        }
        return $data;
    }

    /**
     * 获取充值用户总量 (指定日期)
     * @param null $day
     * @return string
     * @throws \think\Exception
     */
    private function getChargeUserTotal($day = null)
    {

        $filter = [
            'pay_status' => PayStatusEnum::SUCCESS,
            'wxapp_id' => self::$wxapp_id,
            'order_source' => 40,
            'order_status' => ['<>', OrderStatusEnum::CANCELLED],
            'pay_time' =>  [
                ['>=', strtotime($day[0])],
                ['<', strtotime($day[1])],
            ]
        ];

        $num = db('order')
            ->where($filter)
            ->group('user_id')
            ->count();

        return number_format($num);
    }

    /**
     * 获取下单用户总量 (指定日期)
     * @param $days
     * @return array
     * @throws \think\Exception
     */
    private function getPayUser($days)
    {

        $data = [];
        foreach ($days as $day) {
            $data[] = $this->getPayUserTotal($day[0],$day[1]);
        }
        return $data;
    }


    /**
     * 获取下单用户总量 (指定日期)
     * @param null $day
     * @return string
     * @throws \think\Exception
     */
    private function getPayUserTotal($startday = null,$endday = null)
    {

        $commfilter = [
            'pay_status' => PayStatusEnum::SUCCESS,
            'wxapp_id' => self::$wxapp_id,
            'order_status' => ['<>', OrderStatusEnum::CANCELLED],
            'is_delete' => 0,
            'pay_time' =>  [
                ['>=', strtotime($startday)],
                ['<', strtotime($endday)],
            ]
        ];

        $giftsfilter = [
            'pay_status' => PayStatusEnum::SUCCESS,
            'wxapp_id' => self::$wxapp_id,
            'is_delete' => 0,
            'pay_time' =>  [
                ['>=', strtotime($startday)],
                ['<', strtotime($endday)],
            ]
        ];

        //普通订单
        $commUserIds = db('order')
            ->distinct(true)
            ->where($commfilter)
            ->column('user_id');

        //爆品
        $giftsUserIds = db('gifts_order')
            ->distinct(true)
            ->where($giftsfilter)
            ->column('user_id');

        $mergeUserIds = array_merge($commUserIds,$giftsUserIds);

        return count(array_unique($mergeUserIds));
    }



    /**
     * 获取评价总量
     * @return string
     */
    private function getCommentTotal()
    {
        $model = new Comment;
        return number_format($model->getCommentTotal());
    }




    /**
     * 获取订单总量 (指定日期)
     * @param $days
     * @return array
     */
    private function getOrderTotalPriceByDate($days)
    {
        $data = [];
        foreach ($days as $day) {
            $data[] = $this->getOrderTotalPrice($day);
        }
        return $data;
    }

    /**
     * 获取某天的总销售额
     * @param null $day
     * @return string
     */
    private function getOrderTotalPrice($day = null)
    {
        return helper::number2($this->OrderModel->getOrderTotalPrice($day, $day));
    }

    /**
     * 获取某天的下单用户数
     * @param $day
     * @return float|int
     */
    private function getPayOrderUserTotal($startday = null ,$endday = null)
    {

        return number_format($this->OrderModel->getPayOrderUserTotal($startday,$endday));
    }

    /**
     * 获取当天分红金额 (指定日期)
     * @param $days
     * @return array
     * @throws \think\Exception
     */
    private function getRefundTotal($start = null ,$end = null)
    {
        $where = [
            'wxapp_id' => self::$wxapp_id,
            'create_time' =>  [
                ['>=', strtotime($start)],
                ['<', strtotime($end) + 86400],
            ]
        ];


        $refundMoney = db('divide_receives')
            ->where($where)
            ->sum('total_abonus');

        return bcadd($refundMoney,0,2);

    }


    /**
     * 获取当天分红笔数 (指定日期)
     * @param $days
     * @return array
     * @throws \think\Exception
     */
    private function getRefundNum($startday = null,$endtime = null)
    {
        $where = [
            'wxapp_id' => self::$wxapp_id,
            'create_time' =>  [
                ['>=', strtotime($startday)],
                ['<', strtotime($endtime) + 86400],
            ]
        ];
        $refundCount = db('divide_receives')
            ->where($where)
            ->sum('times');

        return $refundCount;
    }



    /**
     * 获取待发放佣金笔数 (指定日期)
     * @param $days
     * @return array
     * @throws \think\Exception
     */
    private function getDealerTotal($startday = null,$endtime = null)
    {
        $where = [
            'wxapp_id' => self::$wxapp_id,
            'is_settled' => 0,
            'create_time' =>  [
                ['>=', strtotime($startday)],
                ['<', strtotime($endtime) + 86400],
            ]
        ];
        $count = db('dealer_order')
            ->where($where)
            ->count();

        return $count;
    }


    /**
     * 获取待发放佣金笔数 (指定日期)
     * @param $days
     * @return array
     * @throws \think\Exception
     */
    private function getDealerSetted($startday = null,$endtime = null)
    {
        $where = [
            'is_settled' => 1,
            'wxapp_id' => self::$wxapp_id,
            'create_time' =>  [
                ['>=', strtotime($startday)],
                ['<', strtotime($endtime) + 86400],
            ]
        ];

        $money = db('dealer_order')
            ->where($where)
            ->sum('first_money');

        return $money;
    }




    /**
     * 获取当月第一天和最后一天
     * @param $days
     * @return array
     * @throws \think\Exception
     */
    private function getthemonth($date)
    {
        $firstday = date('Y-m-01', strtotime($date));
        $lastday = date('Y-m-d', strtotime("$firstday +1 month -1 day"));
        return array($firstday,$lastday);
    }



    /**
     * 时间分割
     * @param null $day
     * @return string
     */
    private function getSchemeDate($start = null, $end = null, $nums = 4, $format=true)
    {

        $start = strtotime($start);
        $end   = strtotime($end)+ 86400;
        $parts = ($end - $start)/$nums;
        $last  = ($end - $start)%$nums;
        if ( $last > 0) {
            $parts = ($end - $start - $last)/$nums;
        }
        for ($i=1; $i <= $nums; $i++) {
            $_end  = $start + $parts * $i;
            $arr[] = array($start + $parts * ($i-1), $_end);
        }
        $len = count($arr)-1;
        $arr[$len][1] = $arr[$len][1] + $last;
        if ($format) {
            foreach ($arr as $key => $value) {
                $arr[$key][0] = date("Y-m-d H:00:00", $value[0]);
                $arr[$key][1] = date("Y-m-d H:00:00", $value[1]);
            }
        }
        return $arr;
    }


    /**
     * 获取两个时间段的日期
     * @param $days
     * @return array
     * @throws \think\Exception
     */
    private function periodDate($start_time,$end_time){

        $start_time = strtotime($start_time);
        $end_time = strtotime($end_time);
        $i=0;
        while ($start_time<=$end_time){
            $arr[$i]=date('Y-m-d',$start_time);
            $start_time = strtotime('+1 day',$start_time);
            $i++;
        }

        return $arr;
    }

}